﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using CoreEx.DynamicInvoker;
using LinFu.AOP.Interfaces;
using LinFu.Proxy.Interfaces;

namespace CoreEx.Database.Persistence
{
    public class EnumeratorInvokeWrapper : IInvokeWrapper
    {
        private IEnumerator _target;
        private IDictionary<object, object> _proxyList;
        private IChangeTracker _changeTracker;
        private Type _elementType;

        public EnumeratorInvokeWrapper(IEnumerator target, IDictionary<object, object> proxyList, IChangeTracker changeTracker, Type elementType)
        {
            _elementType = elementType;
            _target = target;
            _proxyList = proxyList;
            _changeTracker = changeTracker;
        }

        public void BeforeInvoke(IInvocationInfo info){}
        

        public void AfterInvoke(IInvocationInfo info, object returnValue){}
        

        public object DoInvoke(IInvocationInfo info)
        {
            if (info.TargetMethod.Name == "get_Current")
            {
                var returnValue = info.TargetMethod.DynamicInvoke(_target, info.Arguments);
                var proxyInstance = GetProxyInstance(returnValue);
                return proxyInstance;
            }
            
            return info.TargetMethod.DynamicInvoke(_target, info.Arguments);
        }

        public object GetProxyInstance(object target)
        {
            if (target == null)
                return null;

            if (!_proxyList.ContainsKey(target))
            {
                var proxy = CreateProxy(target);
                _proxyList.Add(target, proxy);
            }
            return _proxyList[target];
        }


        private object CreateProxy(object target)
        {
            return _changeTracker.ProxyFactory.CreateProxy(_elementType,
                new ObjectInvokeWrapper(target, _changeTracker), typeof(INotifyPropertyChanged));
        }

    }
}
